上一篇我們看了 Gaussian Filter。
它透過調整每個 Pixel 的權重,讓離中心越近的 Pixel 擁有越大的影響力,因此通常比 Mean Filter 更能保留影像細節。
但事實上,Mean Filter 和 Gaussian Filter 雖然權重不同,本質上卻都做著同一件事情,也就是在「平均」周圍的 Pixel。
如果遇到一般的隨機雜訊,這種方法通常效果不錯。
但如果雜訊是一顆一顆突然出現的黑點或白點呢?
平均真的還是最好的方法嗎?
聽這雜訊的名字,是不是大概能想出長怎麼樣呢?
簡單來說,就是在圖片上隨機出現白色(鹽)和黑色(胡椒)的雜訊。
先來看看下面這個例子。
20 22 21
23 255 24
22 23 21
中間突然出現一個 255。
很明顯,它和周圍的 Pixel 完全不一樣。
這種只有少數 Pixel 變成全黑(0)或全白(255)的雜訊,稱為 Salt-and-Pepper Noise(椒鹽雜訊)。
它可能來自感測器錯誤、影像傳輸過程中的干擾,或是儲存時的資料損壞。
Mean Filter 會把九個 Pixel 全部平均。
(20 + 22 + 21
+23 +255 +24
+22 +23 +21) / 9
最後得到大約:
48
255 的確被降低了。
但是新的 Pixel 還是比周圍亮很多。
因為平均值很容易受到極端值影響,只要其中一個 Pixel 特別大或特別小,結果就會被拉走。
既然 255 明顯和其他 Pixel 不一樣,那是不是乾脆不要拿它來平均?
而 Median Filter 的做法就是不要算平均,而是找中位數(Median)。
以剛剛的例子來說:
先把九個 Pixel 排序。
20
21
21
22
22
23
23
24
255
排好之後,取中間那一個。
23
新的 Pixel 就變成 23。
原本突兀的白點就直接被去除了。
因為中位數只看排序後的位置,並不會受到極端值的大小影響。
不管最後一個值是:
255
還是:
1000
只要它還排在最後,中位數都不會改變。
因此,Median Filter 對這種單點雜訊通常會有非常好的效果。
OpenCV 已經提供了 Median Filter。
使用方式很簡單。
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("salt_and_pepper_noise.png")
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
result = cv2.medianBlur(img, 5)
其中的 5 表示使用 5×5 的鄰域。
OpenCV 會自動取出每個 Pixel 周圍的數值,排序後選出中位數。
接著比較原圖和結果。
plt.figure(figsize=(10,5))
plt.subplot(1,2,1)
plt.imshow(img)
plt.title("Original")
plt.axis("off")
plt.subplot(1,2,2)
plt.imshow(result)
plt.title("Median Filter")
plt.axis("off")
plt.tight_layout()
plt.show()
結果:

如果圖片中有不少椒鹽雜訊,通常可以看到明顯改善。
雖然三者都屬於平滑濾波,但它們的思考方式並不相同。
| Filter | 核心想法 | 適合處理 |
|---|---|---|
| Mean Filter | 所有 Pixel 一起平均 | 一般平滑、降低隨機雜訊 |
| Gaussian Filter | 距離越近權重越大 | 保留較多細節,同時降低雜訊 |
| Median Filter | 不平均,直接取中位數 | 椒鹽雜訊(Salt-and-Pepper Noise) |
可以發現,Median Filter 是目前介紹的三種方法中,唯一不需要做加權平均的濾波方式。
它完全改變了計算新 Pixel 的方式,因此對某些特殊雜訊有更好的效果。
Median Filter 當然還是有缺點的。
由於需要先把每個鄰域的 Pixel 排序,所以相比 Mean Filter 和 Gaussian Filter,它通常需要更多的計算。
另外,如果圖片本身沒有明顯的椒鹽雜訊,Median Filter 的效果未必會比 Gaussian Filter 更好。
因此,在實際應用中,還是需要根據影像的特性選擇合適的濾波方法。
到今天為止,我們介紹了三種常見的平滑濾波方法。
它們都希望降低雜訊,但採用了不同的策略。
到目前為止,我們做的都是讓圖片變得更平滑。
但如果今天的目標不是消除雜訊,而是找出圖片中真正重要的資訊,例如物體的輪廓,又該怎麼做?
下一篇開始,我們就會從「平滑」走向另一個重要主題:
Image Gradient(影像梯度)。
看看電腦是如何找出圖片中的邊緣。